import { ModelData } from "@/constants/types";
import { ConstraintPaneModel } from "./ConstraintPaneModel";
import { LegendPaneModel } from "./LegendPaneModel";
import { GroupPaneModel } from "./GroupPaneModel";
import { PropertyPaneModel } from "./PropertyPaneModel";
import { TagsPaneModel } from "./TagsPaneModel";
import { ItemFlowPaneModel } from "./ItemFlowPaneModel";
import { markRaw, reactive } from "vue";
import MPropertyPane from "@/modules/model/comps/station/sider/attribute/PropertyPane.vue";
import MPropertySlot from "@/modules/model/comps/station/sider/attribute/PropertySlot.vue";
import MNumberPart from "@/modules/model/comps/station/sider/attribute/NumberPartPane.vue";
import MPropertyTags from "@/modules/model/comps/station/sider/attribute/PropertyTag.vue";
import MPropertyLegend from "@/modules/model/comps/station/sider/attribute/PropertyLegend.vue";
import MPropertyGroup_ from "@/modules/model/comps/station/sider/attribute/PropertyGroup.vue";
import MPropertyConstraint from "@/modules/model/comps/station/sider/attribute/PropertyConstraint.vue";
import MHyperlink from "@/modules/model/comps/station/sider/attribute/Hyperlink.vue";
import MItemFlow from "@/modules/model/comps/station/sider/attribute/PropertyItemFlow.vue";

import { modelService } from "@/modules/model/service";
import { MetaclassType } from "@/constants/MetaclassType";

import { AttributeTabKey, HiddenStatus, ModelFrom } from "@/constants/Enums";
import { SlotsPaneModel } from "./SlotsPaneModel";
import { BehaviorsPaneModel } from "./BehaviorsPaneModel";
import { PaneModel } from "./PaneModel";
import { HyperlinkPaneModel } from "./HyperlinkPaneModel";
import { ProjectState } from "@/constants/constants";
import { PropertyGroupInfo } from "../types";
import { Project } from "@/modules/model/project/Project";
import { debouncePromise } from "@/util/common";

import { StType } from "@/constants/StType";
import { NumberPartModel } from "./NumberPartModel";
const MPropertyGroup = markRaw(MPropertyGroup_);

// 固定的tabs
export const tabList: TabItem[] = [
  { name: "属性", key: AttributeTabKey.Properties, comp: markRaw(MPropertyPane), visible: true },
  { name: "插槽", key: AttributeTabKey.Slots, comp: markRaw(MPropertySlot), visible: false },
  { name: "标签", key: AttributeTabKey.Tags, comp: markRaw(MPropertyTags), visible: false },
  { name: "图例项", key: AttributeTabKey.Legend, comp: markRaw(MPropertyLegend), visible: false },
  { name: "约束", key: AttributeTabKey.Constraints, comp: markRaw(MPropertyConstraint), visible: false },
  { name: "导航", key: AttributeTabKey.Hyperlink, comp: markRaw(MHyperlink), visible: false },
  { name: "项流", key: AttributeTabKey.ItemFlow, comp: markRaw(MItemFlow), visible: false },
  { name: "编号属性", key: AttributeTabKey.NumberPart, comp: markRaw(MNumberPart), visible: false }
];

// 10个以内的实例自动查询公共属性，超过10个需要用户手动点击显示属性
export const MAX_AUTO_SHOW_INSTANCE_IDS = 10;

const showItemFlowMetaClass = [MetaclassType.Connector, MetaclassType.ObjectFlow, MetaclassType.ControlFlow, MetaclassType.Message];

export const showLevelOptions = [
  {
    value: 1,
    label: "标准"
  },
  {
    value: 2,
    label: "专家"
  },
  {
    value: 3,
    label: "全部"
  }
];

export function getLevelName(level: number) {
  return showLevelOptions.find(it => it.value === level)?.label || "";
}

type TabItem = {
  key: string;
  name: string;
  comp: any;
  visible: boolean;
};

export class AttributeTabsData {
  projectId?: string;
  modelId?: string;
  modelIds?: string[];
  showProperty = false; // 选择模型超过十个以上的需要用户手动点击查询属性才会去查询
  modelData?: ModelData;
  sortByNameActive?: boolean;
  filterCommentActive?: boolean; // 过滤注释
  tabItems: TabItem[] = tabList.map(it => ({ ...it }));
  activeTab: string = AttributeTabKey.Properties;
  activeProperty = "";
  groupTabsItems: TabItem[] = [];

  isModelDisabled?: boolean;
  tipsVisible = false;
  searchActive = false;
  searchQuery = "";
  get showLevel() {
    return app.global.attributeShowLevel;
  }

  height = 400;
  originHeight = 0;
  mouseStartY = 0;
  hasDragged = false;
  minHeight = 120;

  customUI: any;
  expandActive = false;
  shrinkActive = false;
  nameColumnWidth = 110;
}

/**
 * 容器
 */
export class AttributeTabsModel {
  projectId: string;
  data: AttributeTabsData = reactive(new AttributeTabsData());
  ignoreJavaModelChange = false;

  get modelId(): string | undefined {
    return this.data.modelId;
  }

  propertyPaneModel = new PropertyPaneModel(this);

  tagsPaneModel = new TagsPaneModel(this);

  constraintsPaneModel = new ConstraintPaneModel(this);

  itemFlowPaneModel = new ItemFlowPaneModel(this);
  numberPartModel = new NumberPartModel(this);
  groupPaneModel = new GroupPaneModel(this);
  slotPaneModel = new SlotsPaneModel(this);
  behaviorsPaneModel = new BehaviorsPaneModel(this);
  hyperlinkPaneModel = new HyperlinkPaneModel(this);
  legendPaneModel = new LegendPaneModel(this);

  paneModelMap = new Map<string, PaneModel>();
  constructor(projectId: string, public project?: Project) {
    this.projectId = projectId;
    this.data.projectId = projectId;
    this.paneModelMap.set(AttributeTabKey.Properties, this.propertyPaneModel);
    this.paneModelMap.set(AttributeTabKey.Slots, this.slotPaneModel);

    this.paneModelMap.set(AttributeTabKey.Tags, this.tagsPaneModel);

    this.paneModelMap.set(AttributeTabKey.Legend, this.legendPaneModel);
    this.paneModelMap.set(AttributeTabKey.Constraints, this.constraintsPaneModel);

    this.paneModelMap.set(AttributeTabKey.Behaviors, this.behaviorsPaneModel);
    this.paneModelMap.set(AttributeTabKey.Hyperlink, this.hyperlinkPaneModel);
    this.paneModelMap.set(AttributeTabKey.ItemFlow, this.itemFlowPaneModel);
    this.paneModelMap.set(AttributeTabKey.NumberPart, this.numberPartModel);
  }
  toggleSortByNameActive() {
    this.data.sortByNameActive = !this.data.sortByNameActive;
  }
  toggleFilterCommentActive() {
    this.data.filterCommentActive = !this.data.filterCommentActive;
  }

  updateTabsVisible() {
    if (this.data.modelIds && this.data.tabItems) {
      this.data.tabItems.forEach(it => (it.visible = it.key === AttributeTabKey.Properties));
      return;
    }
    // slot tab显示
    const isSpec = this.data.modelData?.metaclass === MetaclassType.InstanceSpecification;
    const slotTab = this.data.tabItems.find(it => it.key === AttributeTabKey.Slots);
    if (slotTab) {
      slotTab.visible = !!isSpec;
    }

    // tags tab显示
    const tagsTab = this.data.tabItems.find(it => it.key === AttributeTabKey.Tags);
    if (tagsTab) {
      tagsTab.visible = (this.data.modelData?.sts?.length as number) > 0;
    }

    // attrConstraint tab显示
    const attrConstraintTab = this.data.tabItems.find(it => it.key === AttributeTabKey.Constraints);

    if (app.global.isIpcWindow) {
      attrConstraintTab!.visible = true;
    }
    // Behaviors tab显示
    const behaviorsPane = this.data.tabItems.find(it => it.key === AttributeTabKey.Behaviors);
    if (behaviorsPane && app.global.isIpcWindow) {
      behaviorsPane.visible = true;
    }

    const hyperlinkPane = this.data.tabItems.find(it => it.key === AttributeTabKey.Hyperlink);
    if (app.global.isIpcWindow && hyperlinkPane) {
      hyperlinkPane.visible = true;
    }

    // proeprty
    const propertyTab = this.data.tabItems.find(it => it.key === AttributeTabKey.Properties);

    if (propertyTab) {
      propertyTab.visible = true;
    }

    // itemflow
    const itemFlowPane = this.data.tabItems.find(it => it.key === AttributeTabKey.ItemFlow);
    if (
      app.global.isIpcWindow &&
      this.data.modelData?.metaclass &&
      showItemFlowMetaClass.includes(this.data.modelData?.metaclass) &&
      itemFlowPane
    ) {
      itemFlowPane.visible = true;
    } else {
      itemFlowPane && (itemFlowPane.visible = false);
    }

    // 图例项
    const legendTab = this.data.tabItems.find(it => it.key === AttributeTabKey.Legend);
    if (app.global.isIpcWindow && this.data.modelData?.baseSt === StType["Customization::Legend"]) {
      legendTab!.visible = true;
    }

    const activeTab =
      this.data.tabItems.find(it => it.key === this.data.activeTab) || this.data.groupTabsItems.find(it => it.key === this.data.activeTab);
    if (!activeTab || !activeTab.visible) {
      this.data.activeTab = this.data.tabItems[0]?.key;
    }

    // 编号属性
    const numberPartPane = this.data.tabItems.find(it => it.key === AttributeTabKey.NumberPart);
    if (numberPartPane) {
      numberPartPane.visible = Boolean(
        this.data.modelData?.sts.includes(StType["Customization::NumberingScheme"]) ||
          this.data.modelData?.baseSt === StType["Customization::NumberingScheme"]
      );
    }
  }

  showCommonProperty() {
    this.propertyPaneModel.loading = true;
    this.data.showProperty = true;

    this.freshTableData();
  }

  /**
   * 更改当前模型时触发
   * @param projectId
   * @param modelId
   */
  async onCurModelChange(projectId: string, modelId: string, modelIds?: string[]) {
    // console.log(modelId, modelIds);
    if (this.data.modelId === modelId && this.data.modelIds?.toString === modelIds?.toString()) return;
    this.data.projectId = projectId;
    this.data.modelId = modelId;
    this.data.modelIds = modelIds;
    if (modelIds && modelIds.length > MAX_AUTO_SHOW_INSTANCE_IDS) {
      this.data.showProperty = false;
    } else {
      this.data.showProperty = true;
    }
    await this.freshTableData();
  }
  freshTableData = debouncePromise(async function (this: AttributeTabsModel) {
    const { projectId, modelId, modelIds } = this.data;
    if (!projectId || (!modelId && (!modelIds || !modelIds.length))) {
      this.clearData();
    } else {
      const project = app.projectManager.getProject(projectId);
      if (!project) return;
      if (project.ui.closeState !== ProjectState.OPENED) return;

      if (!this.data.showProperty) {
        this.updateTabsVisible();
        return;
      }
      await this.loadTabsData(projectId, modelId, modelIds);
      this.updateModelDisabled(projectId, modelId, modelIds);

      // 属性tab是永远可见的，如果上一个的tab不可见，切到属性tab
      const attrConstraintTab = this.data.tabItems.find(it => it.key === this.data.activeTab);
      if (!attrConstraintTab?.visible) {
        this.data.activeTab = AttributeTabKey.Properties;
      }

      const model = this.getActiveTabModel();
      await model.fresh();
      const otherModels = this.paneModelMap.filter(it => it !== model);
      otherModels.forEach(it => it.clear());
    }
  }, 200);
  async loadTabsData(projectId: string, modelId?: string, modelIds?: string[]) {
    if (!projectId || (!modelId && !modelIds)) return;

    let groups: PropertyGroupInfo[] = [];
    if (!modelIds || !modelIds.length) {
      // 选中单个的情况
      const modelDataForTabs = await modelService.getModelDataForTabs(projectId, modelId!);
      groups = modelDataForTabs.groups;
      this.data.modelData = modelDataForTabs.model;
    } else {
      // 选中多个的情况
      const modelDatas = await modelService.getModelDatas(projectId, modelIds);
      // 为多个元素模拟一个假的modelData
      this.data.modelData = { id: "multiple", modelTypeCnName: "多个元素" } as unknown as ModelData;
      if (modelDatas.every(it => it.modelTypeCnName === modelDatas[0].modelTypeCnName)) {
        this.data.modelData.modelTypeCnName = modelDatas[0].modelTypeCnName;
      }
      if (modelDatas.some(it => it.hiddenStatus === HiddenStatus.HIDDEN_IN_ENCAP)) {
        this.data.modelData.hiddenStatus = HiddenStatus.HIDDEN_IN_ENCAP;
      } else if (modelDatas.some(it => it.hiddenStatus === HiddenStatus.SHOW_IN_ENCAP)) {
        this.data.modelData.hiddenStatus = HiddenStatus.SHOW_IN_ENCAP;
      }
      this.data.modelData.from = Math.min(...modelDatas.map(it => Number(it.from))) as unknown as ModelFrom;
    }

    // 分组tabs展示
    this.data.groupTabsItems = groups.map(it => ({
      key: it.groupId,
      name: it.name,
      visible: true,
      comp: MPropertyGroup
    }));
    this.updateTabsVisible();
  }

  async updateModelDisabled(projectId: string, modelId?: string, modelIds?: string[]) {
    if (modelIds && modelIds.length) {
      // TODO 这里要不要换成批量接口
      for (let id of modelIds) {
        const disabled = await modelService.isModelDisabled(id, projectId);
        if (disabled) {
          this.data.isModelDisabled = disabled;
          return;
        }
      }
      this.data.isModelDisabled = false;
    } else {
      this.data.isModelDisabled = await modelService.isModelDisabled(modelId!, projectId);
    }
  }

  async updateTabsHeight(height: number) {
    console.log("updateTabsHeight");
    if (height > app.global.mainWindowHeight - 320) {
      height = app.global.mainWindowHeight - 320;
    }
    this.data.height = Math.max(this.data.minHeight, height);
  }

  async changeActiveTab(key: string, isLoadData = true) {
    this.data.activeTab = key;
    if (isLoadData) {
      const model = this.getActiveTabModel();
      await model.loadDataWhenNotLoad();
    }
  }
  setActiveProperty(key: string) {
    this.data.activeProperty = key;
  }
  getActiveTabModel() {
    const activeTabKey = this.data.activeTab;
    return this.paneModelMap.get(activeTabKey) || this.groupPaneModel;
  }
  setLevel(level: number) {
    const oldLevel = app.global.attributeShowLevel;
    if (oldLevel === level) return;

    app.global.setAttributeShowLevel(level);
    const activeTabKey = this.data.activeTab;

    if (activeTabKey === AttributeTabKey.Properties) {
      const model = this.getActiveTabModel();
      model.fresh();
    }
  }
  setSearchQuery(val) {
    this.data.searchQuery = val;
  }
  //

  toggleTipsVisible() {
    this.data.tipsVisible = !this.data.tipsVisible;
  }
  toggleSearchActive() {
    this.data.searchActive = !this.data.searchActive;
  }

  getVisibleTabs() {
    return [...this.data.tabItems, ...this.data.groupTabsItems].filter(it => it.visible);
  }

  clearData() {
    this.data.modelId = "";
    this.data.modelIds = undefined;
    this.data.modelData = undefined;
    this.paneModelMap.forEach(model => {
      model.clear();
    });
  }

}
